/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#pragma once

#include <Config.h>
#include <math/Vector3.h>
#include <utl.h>
#include <xml/Object.h>
#include <filesystem/String.hpp>
#include "PrimitiveAnimations.h"
//#include "Commands.h"
#include <boost/fusion/container.hpp>

namespace liba
{
namespace animate
{

class Animation : public xml::ObjectANSI
{
	struct TYPES
	{
		enum types
		{
			DOUBLE		= 0,
			VECTOR_3	= 1,
			WSTRING		= 2,
			FS_STRING	= 3,
			//COMMANDS	= 4
		};
	};

	boost::fusion::vector< PrimitiveAnimations< float >
		, PrimitiveAnimations< math::Vector3<float> >
		, PrimitiveAnimations< std::wstring >
		, PrimitiveAnimations< filesystem::String >
		//, Commands
	> env;


	double speed;
	time_float length;
	time_float time;
	bool binded;
public:
	Animation();
	virtual ~Animation();

	bool bind( Node * animation_root, bool recursion );
	time_float get_length()const
	{
		return length;
	}

	/** Time is measured from 0 to get_length() */
	time_float get_time()const
	{
		return time;
	}
	void change_time(time_float time);
	/** returns time remained after reaching the end or 0 otherwise.
		delta_time can be negative to animate backward */
	time_float add_time(time_float delta_time);
	/** cycle the animation. return number of resets to 0
		delta_time can be negative to animate backward. */
	int add_time_cycle(time_float delta_time);

	/** Position is measured from 0 to 1 */
	void change_position(time_float position);
	time_float get_position()const
	{
		return (abs(length) < std::numeric_limits<time_float>::epsilon()) ? 0 : time / length;
	}

	bool is_finished()const
	{
		return abs(time - length) < std::numeric_limits<time_float>::epsilon();
	}

	void SetSpeed(float newSpeed);
	float GetSpeed() const { return (float) speed; }

protected:
	virtual bool on_attribute(xml::Provider * prov, const std::string & name, const std::string & value );
	virtual bool on_node( xml::Provider * prov, const std::string & name );
	virtual bool on_end_node( xml::Provider * prov );
};

} // namespace animate
} // namespace liba
using namespace liba;

